#include "uorb.h"
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "usart.h"

#define orb_printf printf

bool orb_advertise(struct orb_metadata *meta)
{
	if(meta->orb_data == NULL)//is null
	{
		meta->orb_data = malloc( meta->o_size );
		
		if(!meta->orb_data || !meta->o_name) 
		{
			orb_printf("xxxxxxx advertise error,name:%s,data:0x%x\r\n",meta->o_name,meta->orb_data);
			return 0;
		}
	}
	else
	{
		orb_printf("xxxxxxx [%s] already subscribed\r\n",meta->o_name);
		return 0;
	}

	return 1;
}

bool orb_subscribe(struct orb_metadata *meta,uint32_t *id)
{
	struct orb_subscriber *subscriber_next = 0;
	struct orb_subscriber *ptr = 0;

	if(!id)
	{
		orb_printf("xxxxxxx %s already subscribe.\r\n",meta->o_name);
		return 0;
	}
	
	if(!meta)/*-- check -----*/
	{
		orb_printf("xxxxxxx can't subscribe,name:%s\r\n",meta->o_name);
		return 0;
	}
	if(meta->orb_data == 0)/*-- check -----*/
	{
		orb_printf("xxxxxxx must be advertise,name:%s\r\n",meta->o_name);
		*id = 0;
		return 0;
	}
	
	subscriber_next = malloc(sizeof(struct orb_subscriber));
	if(!subscriber_next) 
	{
		orb_printf("xxxxxxsubscriber->[%s] no memery.\r\n",meta->o_name);
		return 0;//no memery
	}
	
	meta->metadata_nums++;

	subscriber_next->next = 0;
	subscriber_next->id = meta->metadata_nums;
	
	*id =  meta->metadata_nums;

	ptr = meta->subscriber_first;
	if(ptr == 0)//the first
	{
		meta->subscriber_first = subscriber_next; 
	}
	else//not for the first time
	{
		while(ptr->next)//find end
		{
			ptr = ptr->next;
		}
		
		ptr->next = subscriber_next;
        ptr->next->next = 0;
	}
	//free(subscriber_next);
	return 1;
}

bool orb_unsubscribe(struct orb_metadata *meta,uint32_t *id)
{
	if(!meta || !(*id)) return 0;
	if(meta->orb_data == 0)/*-- check -----*/
	{
		orb_printf("xxxxxxx must be advertise,then can be unsubscribe ,name:%s\r\n",meta->o_name);
		*id = 0;
		return 0;
	}

	orb_subscriber *ptr = 0;
	ptr = meta->subscriber_first;

	uint16_t orb_cnt = 0;
	orb_cnt++;
	

	while(orb_cnt < *id)
	{
		ptr = ptr->next;

		orb_cnt++;
	}
	
	ptr->id = 0;//clean id
	ptr->flag = 0;
	
	//if(meta->metadata_nums)
	//	meta->metadata_nums--;

    if(meta->metadata_nums == 0)
        meta->subscriber_first = 0;
	
	return 1;
}



bool orb_check(struct orb_metadata *meta,uint32_t id)
{
	if(!meta->orb_data) return 0;//check null

	if(!(id))
	{
		orb_printf("xxxxxxx [%s] please subscribe first.\r\n",meta->o_name);
		return 0;
	}

	uint16_t orb_cnt = 0;
	
	orb_subscriber *ptr = 0;
	ptr = meta->subscriber_first;

	//maybe lock
	orb_cnt++;
	while(orb_cnt < id && ptr)//find id
	{
		ptr = ptr->next;
		
		orb_cnt++;
	}

	if(ptr->id == id && ptr->flag)
	{
		//ptr->id = 0;
		ptr->flag = 0;
		return 1;
	}
	else
		return 0;
}

bool orb_copy(struct orb_metadata *meta,void *buffer)
{
	if(!meta || !meta->orb_data || !buffer) return 0;

	//maybe lock
	memcpy(buffer,meta->orb_data,meta->o_size);
	
	return 1;
}

bool orb_publish(struct orb_metadata *meta,void *structure)
{
	if(!meta->orb_data || !structure) return 0;//check
	
	memcpy(meta->orb_data,structure,meta->o_size);

	uint16_t orb_cnt = 0;
	
	orb_subscriber *ptr = 0;
	ptr = meta->subscriber_first;


	//maybe lock
	while(orb_cnt < meta->metadata_nums && ptr)//find end
	{
		orb_cnt++;
		
		//ptr->id = orb_cnt;
		ptr->flag = 1;
		
		ptr = ptr->next;
	}

	return 1;
}
